2016-09-22 23 views
0

我有記錄的以下csv文件:需要通過讀取csv文件具有隨機列創建熊貓數據幀

  • A 1,B 2,C 10,d 15
  • A 5,d 10 ,G 2
  • d 6,E 7
  • H 7,G 8

我的列標題/名稱是:A,B,C,d,E,F,G

因此,我使用 「read_csv」 之後的初始數據幀變爲:

A  B  C  D  E  F  G 
A 1 B 2 C 10 D 15 NaN NaN NaN 
A 5 D 10 G 2 NaN NaN NaN NaN 
D 6 E 7 NaN NaN NaN NaN NaN 
H 7 G 8 NaN NaN NaN NaN Nan 

的值可以是分開成[柱名] [列值],因此A 1表示COL = A和值= 1,並且d 15意味着山坳= d和值= 15,等等

我想是分配的數值基於該 合適的欄目,有一個數據幀,看起來像這樣:

A  B  C  D  E  F  G 
A 1 B 2 C 10 D 15 NaN NaN NaN 
A 5 Nan NaN D 10 NaN NaN G 2 
NaN NaN NaN D 6 E 7 NaN NaN 
NaN NaN NaN NaN NaN NaN G 8 

甚至更好,僅僅是價值:

A  B  C  D  E  F  G 
1  2  10  15  NaN NaN NaN 
5  Nan NaN 10  NaN NaN 2 
NaN NaN NaN 6  7  NaN NaN 
NaN NaN NaN NaN  NaN NaN 8 

回答

2

您可以通過與apply功能(axis = 1)行中循環,構建了基於分裂後的鍵值對,並且新建系列將通過其索引自動對準各行的熊貓系列,只是請注意這裏沒有F列,但額外有H,不知道它是否是您需要的。但除去H並增加一個額外的NaN F列應該是直截了當:

df.apply(lambda r: pd.Series({x[0]: x[1] for x in r.str.split(' ') 
            if isinstance(x, list) and len(x) == 2}), axis = 1) 


#  A B C D E G H 
#0 1 2 10 15 NaN NaN NaN 
#1 5 NaN NaN 10 NaN 2 NaN 
#2 NaN NaN NaN 6 7 NaN NaN 
#3 NaN NaN NaN NaN NaN 8 7 
+0

這並不在我的數據幀的工作。它給了我IndexError:('列表索引超出範圍',u'發生在索引0') – Michael

+0

我可以想到的幾件事情,當你讀取數據時,可能會有每個字符串的前導或尾隨空格;並且每個字符串可能不會被一個空格隔開,並且每個單元格可能有多個而不是配對值。 – Psidom

+0

責備nan電池,@Psidom。 OP得到一個超出範圍的列表索引,因爲nan不會解析成'.str.split'下的列表。所以你不能索引它(你巧妙地寫'x [0]:x [1]')。我也從來不知道像花括號裏的語法一樣的列表理解。謝謝你的啓發! – Kartik

0

下面是代碼:

res = pd.DataFrame(index=df.index, columns=list('ABCDEFGH')) 

def classifier(row): 
    cols = row.str.split().str[0].dropna().tolist() 
    vals = row.str.split().str[1].dropna().tolist() 
    res.loc[row.name, cols] = vals 

df.apply(classifier, axis=1) 

輸入:

from io import StringIO 
import pandas as pd 
import numpy as np 

data = """A 1, B 2, C 10, D 15 
A 5, D 10, G 2 
D 6, E 7 
H 7, G 8""" 

df = pd.read_csv(StringIO(data), header=None) 
print("df:\n", df) 

res = pd.DataFrame(index=df.index, columns=list('ABCDEFGH')) 

def classifier(row): 
    cols = row.str.split().str[0].dropna().tolist() 
    vals = row.str.split().str[1].dropna().tolist() 
    res.loc[row.name, cols] = vals 
df.apply(classifier, axis=1) 

print("\nres:\n", res) 

輸出:

df: 
    0 1  2  3 
0 A 1 B 2 C 10 D 15 
1 A 5 D 10 G 2 NaN 
2 D 6 E 7 NaN NaN 
3 H 7 G 8 NaN NaN 

res: 
    A B C D E F G H 
0 1 2 10 15 NaN NaN NaN NaN 
1 5 NaN NaN 10 NaN NaN 2 NaN 
2 NaN NaN NaN 6 7 NaN NaN NaN 
3 NaN NaN NaN NaN NaN NaN 8 7 
2

應用解決方案:

使用split用空格,由dropnaset_index刪除NaN行和DataFrame.squeezeDataFrameSeries轉換一列。最後reindex通過新的列名:

print (df.apply(lambda x: x.str.split(expand=True) 
           .dropna() 
           .set_index(0) 
           .squeeze(), axis=1) 
     .reindex(columns=list('ABCDEFGH'))) 

    A B C D E F G H 
0 1 2 10 15 NaN NaN NaN NaN 
1 5 NaN NaN 10 NaN NaN 2 NaN 
2 NaN NaN NaN 6 7 NaN NaN NaN 
3 NaN NaN NaN NaN NaN NaN 8 7 

堆棧解決方案:

使用stack創建Seriessplit用空格和創建新列,新的列名(AB追加列...),以indexset_index,一列DataFrame轉換爲Series通過DataFrame.squeeze,通過reset_index刪除與舊列名的索引值,unstackreindex通過新的列名(將其添加缺少的NaN填列),由astype和最後一個值轉化爲float通過rename_axis(新中pandas0.18.0)刪除列名:

print (df.stack() 
     .str.split(expand=True) 
     .set_index(0, append=True) 
     .squeeze() 
     .reset_index(level=1, drop=True) 
     .unstack() 
     .reindex(columns=list('ABCDEFGH')) 
     .astype(float) 
     .rename_axis(None, axis=1)) 

    A B  C  D E F G H 
0 1.0 2.0 10.0 15.0 NaN NaN NaN NaN 
1 5.0 NaN NaN 10.0 NaN NaN 2.0 NaN 
2 NaN NaN NaN 6.0 7.0 NaN NaN NaN 
3 NaN NaN NaN NaN NaN NaN 8.0 7.0 
+0

好的解決方案!所有在一條線,因爲我們喜歡它! +1 ...另外,我不知道'.str.split'中的'expand' kwag,這將會節省我的解決方案的一條線,並且還可能使操作更快...... – Kartik