我有以下问题:我想将列附加到数据框。这些列是此数据框的另一行中的唯一值,填充此行中此值的出现。它看起来像这样:
df:
Column1 Column2
0 1 a,b,c
1 2 a,e
2 3 a
3 4 c,f
4 5 c,f
我想要的是:
Column1 Column2 a b c e f
0 1 a,b,c 1 1 1
1 2 a,e 1 1
2 3 a 1
3 4 c,f 1 1
4 5 c,f 1 1
(空格可以是nan或0,重要的不是。)
我现在已经编写了一些代码来解决这个问题,但是它不是追加列,而是追加行,这样我的输出就像这样:
Column1 Column2
0 1 a,b,c
1 2 a,e
2 3 a
3 4 c,f
4 5 c,f
a 1 1
b 1 1
c 1 1
e 1 1
f 1 1
代码如下所示:
def NewCols(x):
for i, value in df['Column2'].iteritems():
listi=value.split(',')
for value in listi:
string = value
x[string]=list.count(string)
return x
df1=df.apply(NewCols)
我在这里要做的是遍历数据帧的每一行并以逗号分割Column2中包含的字符串(a,b,c),因此变量listi
然后是包含分隔的字符串值的列表。对于每个值,我想创建一个新列,并在listi
中填充该值的出现次数。我很困惑为什么代码附加行而不是列。有人知道我为什么以及如何纠正这个问题?
答案 0 :(得分:4)
虽然我们可以使用get_dummies
执行此操作,但我们也可以直接欺骗并使用pd.value_counts
:
>>> df = pd.DataFrame({'Column1': {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}, 'Column2': {0: 'a,b,c', 1: 'a,e', 2: 'a', 3: 'c,f', 4: 'c,f'}})
>>> df.join(df.Column2.str.split(",").apply(pd.value_counts).fillna(0))
Column1 Column2 a b c e f
0 1 a,b,c 1 1 1 0 0
1 2 a,e 1 0 0 1 0
2 3 a 1 0 0 0 0
3 4 c,f 0 0 1 0 1
4 5 c,f 0 0 1 0 1
一步一步,我们有
>>> df.Column2.str.split(",")
0 [a, b, c]
1 [a, e]
2 [a]
3 [c, f]
4 [c, f]
dtype: object
>>> df.Column2.str.split(",").apply(pd.value_counts)
a b c e f
0 1 1 1 NaN NaN
1 1 NaN NaN 1 NaN
2 1 NaN NaN NaN NaN
3 NaN NaN 1 NaN 1
4 NaN NaN 1 NaN 1
>>> df.Column2.str.split(",").apply(pd.value_counts).fillna(0)
a b c e f
0 1 1 1 0 0
1 1 0 0 1 0
2 1 0 0 0 0
3 0 0 1 0 1
4 0 0 1 0 1
>>> df.join(df.Column2.str.split(",").apply(pd.value_counts).fillna(0))
Column1 Column2 a b c e f
0 1 a,b,c 1 1 1 0 0
1 2 a,e 1 0 0 1 0
2 3 a 1 0 0 0 0
3 4 c,f 0 0 1 0 1
4 5 c,f 0 0 1 0 1
答案 1 :(得分:2)
使用apply
时,它会为每列调用一次函数,并将该列作为参数。因此,NewCols中的x
将设置为单个列。执行x[string] = list.count(string)
时,您要为该列添加值。由于每个列都会调用apply
,因此您最终会以这种方式将值附加到两列。
apply
不是正确的选择。相反,请使用map
。在这种情况下,您需要做的是编写一个NewCol函数,该函数接受单个Column2
值并返回单行的数据。您可以将其作为dict返回,或者轻松地将其作为类似dict的对象(例如collections.Counter
)。然后,您需要将此新行数据包装到DataFrame中,并使用concat
将其以列方式附加到现有数据。这是一个例子:
def NewCols(val):
return collections.Counter(val.split(','))
>>> pandas.concat([d, pandas.DataFrame.from_records(d.Column2.map(NewCols))], axis=1)
Column1 Column2 a b c e f
0 1 a,b,c 1 1 1 NaN NaN
1 2 a,e 1 NaN NaN 1 NaN
2 3 a 1 NaN NaN NaN NaN
3 4 c,f NaN NaN 1 NaN 1
4 5 c,f NaN NaN 1 NaN 1
对于这个特定的计算,你实际上根本不需要编写自己的函数,因为pandas在split
方法访问器下有.str
内置的操作。所以你可以这样做:
>>> pandas.concat([d, pandas.DataFrame.from_records(d.Column2.str.split(',').map(collections.Counter))], axis=1)
Column1 Column2 a b c e f
0 1 a,b,c 1 1 1 NaN NaN
1 2 a,e 1 NaN NaN 1 NaN
2 3 a 1 NaN NaN NaN NaN
3 4 c,f NaN NaN 1 NaN 1
4 5 c,f NaN NaN 1 NaN 1
答案 2 :(得分:0)
您可以使用以下内容:
import pandas as pd
import sklearn.feature_extraction.text
vect = sklearn.feature_extraction.text.CountVectorizer(binary=True, token_pattern=u'(?u)\\b\\w+\\b')
df = ...
v = [a for a in df['Column2']]
new_df = df.combine_first( pd.DataFrame(vect.fit_transform(v).todense(), columns=vect.get_feature_names()) )
print new_df
干杯!