Python 3.x 熊猫:如何对特定行求和
假设我有一个熊猫数据框,它看起来像这样:Python 3.x 熊猫:如何对特定行求和,python-3.x,pandas,Python 3.x,Pandas,假设我有一个熊猫数据框,它看起来像这样: category sentences Data1 String1 NaN String2 NaN String3 Data2 String1 NaN String4 Data2 String1 NaN String6 NaN String7 Data3 String1 NaN String8 NaN String9 category
category sentences
Data1 String1
NaN String2
NaN String3
Data2 String1
NaN String4
Data2 String1
NaN String6
NaN String7
Data3 String1
NaN String8
NaN String9
category sentences
Data1 String1 String2 String3
Data2 String1 String4
Data2 String1 String6 String7
Data3 String1 String8 String9
我想把它转换成这样:
category sentences
Data1 String1
NaN String2
NaN String3
Data2 String1
NaN String4
Data2 String1
NaN String6
NaN String7
Data3 String1
NaN String8
NaN String9
category sentences
Data1 String1 String2 String3
Data2 String1 String4
Data2 String1 String6 String7
Data3 String1 String8 String9
从标题中可以看到,右栏是完整对话的句子,左栏是它们各自的类别。我在这里试图做的是简单地选择带有NaN
值的行,并将其与前面的行相加,直到到达String1
到目前为止,这对我来说是一个失败,因为我尝试了不同的东西,但仍然没有解决方案。我该怎么做
另一个问题:我选择我的数据帧(我们称之为df
)并选择前3行,然后使用df[0:3].sum()对它们进行求和,它返回系列([],dtype:float64)
。如果我在最后加上.sum(axis=1)
,我得到的每一行都是零。我尝试了.sum(axis=0)
,它返回了系列([],数据类型:float64)
。我还尝试添加iloc
,但得到了相同的结果。所以,任何人都能看出我做错了什么,我应该做什么
TL;DR:我想将字符串从String1
添加到String1
,而不包括最后一个String1
。有可能这样做吗?如果有,怎么做
请注意:很抱歉格式化。我仍然无法适应它…它不是最佳的、非蟒蛇式的、丑陋的!但它确实起到了作用:
import pandas as pd
old_table = pd.read_csv('your_table.csv')
new_table = pd.DataFrame([],columns=('category','sentences'))
for ID,row in old_table.iterrows():
if not pd.isnull(row['category']):
new_table.loc[len(new_table)] = [row['category'],[row['sentences']]]
else:
string = list(new_table.loc[len(new_table)-1]['sentences'])
string.append(row['sentences'])
new_table.loc[len(new_table)-1]['sentences'] = string
print(old_table,'\n====\n',new_table)
它给出:
category sentences
0 One hello
1 NaN my
2 NaN little
3 NaN friend
4 Two hello
5 NaN to
6 NaN you
7 NaN too
====
category sentences
0 One [hello, my, little, friend]
1 Two [hello, to, you, too]
创建一个临时ID列,与category列一起用作组键,然后为每个组添加句子
df=df.copy()
df['ID'] = df.index.to_series()[df.category.notnull()]
df.fillna(method='ffill')\
.groupby(['ID','category'])['sentences']\
.apply(lambda x: ' '.join(x))\
.reset_index()\
.drop('ID',1)
Out[59]:
category sentences
0 Data1 String1 String2 String3
1 Data2 String1 String4
2 Data2 String1 String6 String7
3 Data3 String1 String8 String9
首先使用ffill
(使用方法='ffill')通过arange
中的唯一值创建系列
,其中替换了类别的值
:
s = df['category'].where(df['category'].isnull(), np.arange(len(df.index))).ffill()
0 0
1 0
2 0
3 3
4 3
5 5
6 5
7 5
8 8
9 8
10 8
Name: category, dtype: int64
然后通过s
和:
非常感谢。工作得很有魅力。如果您不介意的话,请回答一个小问题:为什么在'category':'first'
中使用'first'
?因为它是每个组的第一个值,所以组是由s
创建的,因为需要区分category
列的相同值。我明白了。再次感谢你帮助一个新手!没问题,我们每个人都开始了。如果知道,我很高兴能帮上忙;)天气真好!谢谢这一个也有效,除了我必须在每一行中加入列表。但正如你所说,它是有效的。另外,一个快速更正:如果我没有弄错的话,我相信应该是pd.read\u csv
。谢谢你的回复!但不幸的是,它给了我以下错误:SettingWithCopyWarning:试图在数据帧切片的副本上设置一个值。尝试改用.loc[row\u indexer,col\u indexer]=value
这是一条警告消息,有时可能是错误警报。要摆脱它,可以在运行代码之前先执行df=df.copy()。