2016-09-22 20 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